package org.xqh.test.ugreen;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.arronlong.httpclientutil.HttpClientUtil;
import com.arronlong.httpclientutil.common.HttpConfig;
import com.arronlong.httpclientutil.common.HttpHeader;
import com.arronlong.httpclientutil.common.HttpResult;
import com.arronlong.httpclientutil.exception.HttpProcessException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.xqh.utils.http.FxHttpClientUtils;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;

/**
 * @ClassName UGreenApiCallUtils
 * @Description TODO
 * @Author xuqianghui
 * @Date 2023/11/16 17:46
 * @Version 1.0
 */
@Slf4j
public class UGreenApiCallUtils {

    public final static String REQUEST_HEAD_SIGN = "sign";
    public final static String REQUEST_HEAD_TS = "ts";
    public final static String REQUEST_HEAD_ACCESS_TYPE = "at";
    public final static String REQUEST_HEAD_ACCESS_KEY = "ak";

    public final static String REQUEST_HEAD_MAC = "mac";

    private final static Charset CHARSET = StandardCharsets.UTF_8;

    public final static String test_mac = "98:6E:E8:23:85:93";

    public static String deviceCallCloudApi(Object dto, String api, String secretKey, String accessKey){
        return deviceCallCloudApi(dto, api, secretKey, accessKey, "");
    }

    public static String deviceCallCloudApi(Object dto, String api, String secretKey, String accessKey, String accessType){
        String ts = String.valueOf(System.currentTimeMillis() / 1000);
        String json = buildReqJsonWithSign(dto, accessKey, ts, test_mac, secretKey, accessType);
        HttpRequest httpRequest = HttpUtil.createPost(api);
        httpRequest.body(json);
        httpRequest.contentType("application/json");

        HttpResponse response = httpRequest.execute();
//        log.info("call api result: ===> {}",response.body());
        return response.body();
    }

    public static String buildReqJsonWithSign(Object dto, String accessKey, String ts, String mac, String secretKey, String accessType){
        JSONObject json = JSON.parseObject(JSON.toJSONString(dto));
        json.put(REQUEST_HEAD_ACCESS_KEY, accessKey);
        json.put(REQUEST_HEAD_TS, ts);
        json.put(REQUEST_HEAD_MAC, mac);
        String sign = createSignNew(json, secretKey);
        json.put(REQUEST_HEAD_SIGN, sign);
        if(StringUtils.isNotBlank(accessType)) {
            json.put(REQUEST_HEAD_ACCESS_TYPE, accessType);
        }
        return json.toJSONString();
    }

    /**
     *
     * @param params
     * @param secretKey
     * @param <T>
     * @return
     */
    public static <T> String createSignNew(final JSONObject params, String secretKey) {
        Map<String, Object> newParams = new HashMap<>();//复制一个 map 进行签名校验
        newParams.putAll(params);
        //除去空值请求参数
        HashMap<String, String> newRequestParams = removeEmptyParam(newParams);

        String strUrlParams = parseUrlString(newRequestParams);

        //4、最后拼接上secretKey得到字符串stringSignTemp
        String stringSignTemp = MessageFormat.format("{0}&SecretKey=", strUrlParams);
        String lastSignStr = stringSignTemp.concat(secretKey);
        //5、对stringSignTemp进行MD5运算，得到sign值
        String signRet = DigestUtils.md5Hex(lastSignStr.getBytes(CHARSET));
        return signRet;
    }

    private static String parseUrlString(final HashMap<String, String> requestMap) {
        List<String> keyList = new ArrayList<>(requestMap.keySet());
        Collections.sort(keyList);

        List<String> entryList = new ArrayList<>();
        for (String key : keyList) {
            String value = requestMap.get(key);
            entryList.add(MessageFormat.format("{0}={1}", key, value));
        }
        return String.join("&", entryList);
    }

    private static HashMap<String, String> removeEmptyParam(final Map<String, Object> params) {
        HashMap<String, String> newParams = new HashMap<>(10);
        if (params == null || params.size() <= 0) {
            return newParams;
        }
        for (String key : params.keySet()) {
            if(params.get(key) instanceof JSONObject || params.get(key) instanceof JSONArray){
                //值 为对象/数组 的 参数 不处理
                continue;
            }
            String value = String.valueOf(params.get(key));
            if(StringUtils.isEmpty(value)){
                continue;
            }
            newParams.put(key, value);
        }
        return newParams;
    }

    public static String callCloudApiWithSign(Object dto, String api, String secretKey, String accessKey, String accessType){
        String jsonPar = JSON.toJSONString(dto);
        String ts = String.valueOf(System.currentTimeMillis() / 1000);
        String signRet = buildSignValue(jsonPar, secretKey);
        Header[] headers = buildReqHeaders4Center(accessKey, accessType, ts, signRet);
        HttpConfig config = FxHttpClientUtils.getPostJsonConfig(api, headers, jsonPar);

        try {
            HttpResult httpRet = HttpClientUtil.sendAndGetResp(config);
            log.info("call api result: {}", httpRet.getResult());
            return httpRet.getResult();
        } catch (HttpProcessException e) {
            throw new RuntimeException(e);
        }
    }

    private static Header[] buildReqHeaders4Center(String ak, String type, String ts, String sign) {
        Header[] result = HttpHeader.custom()
                .other(REQUEST_HEAD_ACCESS_KEY, ak)
                .other(REQUEST_HEAD_ACCESS_TYPE, type)
                .other(REQUEST_HEAD_TS, ts)
                .other(REQUEST_HEAD_SIGN, sign)
                .build();
        return result;
    }

    private static String buildSignValue(String paramJson, String signSecret) {
        Map requestMap = JSONObject.parseObject(paramJson, Map.class);
        String signRet = CertificateUtils.createSignForCloud(requestMap, signSecret);
        return signRet;
    }


    @Data
    public static class CallResultModel{
        private boolean success;
        private String data;
        private String msg;
    }



    public static CallResultModel checkCallResult(HttpResult httpResult){
        CallResultModel result = new CallResultModel();
        if(StringUtils.isNotEmpty(httpResult.getResult())){
            JSONObject retJson = JSON.parseObject(httpResult.getResult());
            if(Objects.nonNull(retJson)){
                if(retJson.containsKey("code") && retJson.getInteger("code") == 200){
                    result.setSuccess(true);
                    if(retJson.containsKey("data")){
                        result.setData(retJson.getString("data"));
                    }
                }
                result.setMsg(retJson.getString("msg"));
            }
        }
        return result;
    }

    public static CallResultModel checkCallResult(HttpResponse response){
        CallResultModel result = new CallResultModel();
        if(StringUtils.isNotEmpty(response.body())){
            JSONObject retJson = JSON.parseObject(response.body());
            if(Objects.nonNull(retJson)){
                if(retJson.containsKey("code") && retJson.getInteger("code") == 200){
                    result.setSuccess(true);
                    if(retJson.containsKey("data")){
                        result.setData(retJson.getString("data"));
                    }
                }
                result.setMsg(retJson.getString("msg"));
            }
        }
        return result;
    }

}
